package com.mjk.common.util;


import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileNameUtil;
import com.mjk.common.tools.logger.BizLogger;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.*;

public class FileUtils extends FileUtil {

    /**
     * 将String写入文件，覆盖模式，字符集为UTF-8
     *
     * @param filepath
     * @param content
     */
    public static void write2File(String filepath, String content) {
        writeUtf8String(content, filepath);
    }

    /**
     * 将内容写入到指定目录的指定文件中 默认为覆盖模式
     *
     * @param dir      文件夹目录
     * @param fileName 文件名称
     * @param content  写入内容
     */
    public static void write2File(String dir, String fileName, String content) {
        write2File(dir, fileName, content, false);
    }

    /**
     * 将内容写入到指定文件夹下的指定文件中 可以指定是否是覆盖还是追加模式
     *
     * @param dir      文件路径
     * @param fileName 文件名称
     * @param content  写入内容
     * @param append   true追加模式 false覆盖模式
     */
    public static void write2File(String dir, String fileName, String content, boolean append) {
        if (append) {
            appendUtf8String(content, dir + fileName);
        } else {
            writeUtf8String(content, dir + fileName);
        }
    }

    /**
     * 是否是文件夹
     *
     * @param path
     */
    public static boolean isDir(String path) {
        return FileUtil.isDirectory(new File(path));
    }

    /**
     * 文件是否存在
     *
     * @param filePath 文件路径
     */
    public static boolean isExit(String filePath) {
        return exist(filePath);
    }

    /**
     * 创建路径
     *
     * @param filePath
     */
    public static void creatDir(String filePath) {
        File file = new File(filePath);
        if (!file.exists())
            file.mkdir();
    }

    /**
     * 按照时间排序 只保留num个文件
     *
     * @param filePath
     * @param num
     */
    public static void deleteOldFile(String filePath, int num) {
        File directory = new File(filePath); // 替换为你的目录路径
        File[] files = directory.listFiles();
        if (files != null) {
            // 按文件最后修改时间排序
			Arrays.sort(files, (f1, f2) -> {
				long diff = f1.lastModified() - f2.lastModified();
				if (diff > 0) return 1;
				else if (diff == 0) return 0;
				else return -1;
			});
            // 假设我们要保留最新的3个文件
            for (int i = 0; i < files.length - num; i++) {
                File file = files[i];
                del(file.getAbsolutePath());
            }
        }
    }

    /**
     * 获取指定目录下指定后缀的文件名称 如果filtername为空，获取所有
     *
     * @param dir
     * @param filterName
     * @return
     */
    public static List<File> loopFiles(String dir, String filterName) {
        return loopFiles(new File(dir),pathname -> {
			if (ObjectUtils.isEmpty(filterName)) {
				return true;
			}
			return pathname.getName().endsWith(filterName);
		});
    }

    /**
     * 获取文件名
     *
     * @param filePath
     * @return
     */
    public static String getFileName(String filePath) {
        return FileNameUtil.mainName(filePath);
    }

    /**
     * 获取文件的字节数据
     *
     * @param filePath
     * @return
     */
    public static byte[] getFileByte(String filePath) {
        File file = (file(filePath));
        return cn.hutool.core.io.file.FileReader.create(file).readBytes();
    }

    public static byte[] getFileByte(String filePath, String endcode) {
        File file = (file(filePath));
        return cn.hutool.core.io.file.FileReader.create(file).readBytes();
    }

    /**
     * 将InputStream装换成某种字符编码的String
     *
     * @param in
     * @param encoding
     * @return
     */
    public static String inputStreamTOString(InputStream in, String encoding) {
        String res = null;
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        byte[] data = new byte[1024];
        int count;
        try {
            while ((count = in.read(data, 0, 1024)) != -1) {
                outputStream.write(data, 0, count);
            }
        } catch (Exception e) {
            BizLogger.error(e);
        }
        try {
            res = outputStream.toString(encoding);
        } catch (UnsupportedEncodingException e) {
            BizLogger.error(e);
        }
        return res;
    }

    /**
     * 计算大文件需要切割成多少个小文件
     *
     * @param fileSize 每个文件的大小
     */
    private static int getFileCount(FileInputStream fis, long fileSize) throws IOException {
        FileChannel inputChannel = fis.getChannel();
        long totalsize = inputChannel.size();
        return (int) ((totalsize % fileSize) > 0 ? (totalsize / fileSize) + 1 : (totalsize / fileSize));
    }

    /**
     * 文件切分
     *
     * @param filePath  文件路径
     * @param countSize 文件大小
     */
    public static List<String> splitFile(String filePath, long countSize) {
        FileOutputStream fos = null;
        try (
                FileInputStream fis = new FileInputStream(filePath)
        ) {
            int fileCount = getFileCount(fis, countSize);
            FileChannel inputChannel = fis.getChannel();
            final long fileSize = inputChannel.size();
            long average = fileSize / fileCount;// 平均值
            long bufferSize = 200; // 缓存块大小，自行调整
            ByteBuffer byteBuffer = ByteBuffer.allocate(Integer.parseInt(bufferSize + "")); // 申请一个缓存区
            long startPosition = 0; // 子文件开始位置
            long endPosition = average < bufferSize ? 0 : average - bufferSize;// 子文件结束位置
            List<String> fileNames = new ArrayList<>();
            if (fileCount > 1) {
                for (int i = 0; i < fileCount; i++) {
                    if (i + 1 != fileCount) {
                        int read = inputChannel.read(byteBuffer, endPosition);// 读取数据
                        readW:
                        while (read != -1) {
                            byteBuffer.flip();// 切换读模式
                            byte[] array = byteBuffer.array();
                            for (int j = 0; j < array.length; j++) {
                                byte b = array[j];
                                if (b == 10 || b == 13) { // 判断\n\r
                                    endPosition += j;
                                    break readW;
                                }
                            }
                            endPosition += bufferSize;
                            byteBuffer.clear(); // 重置缓存块指针
                            read = inputChannel.read(byteBuffer, endPosition);
                        }
                    } else {
                        endPosition = fileSize; // 最后一个文件直接指向文件末尾
                    }
                    String tmpFileName = filePath.split("\\.")[0] + (i + 1) + "." + filePath.split("\\.")[1];
                    fileNames.add(tmpFileName);
                    fos = new FileOutputStream(tmpFileName);
                    FileChannel outputChannel = fos.getChannel();
                    inputChannel.transferTo(startPosition, endPosition - startPosition, outputChannel);// 通道传输文件数据
                    outputChannel.close();

                    startPosition = endPosition + 1;
                    endPosition += average;
                }
            } else {
                fileNames.add(filePath);
            }
            inputChannel.close();
            return fileNames;
        } catch (Exception e) {
            BizLogger.error(e);
        } finally {
            try {
                if (null != fos) {
                    fos.close();
                }
            } catch (Exception e) {
                BizLogger.error(e);
            }
        }
        return Collections.emptyList();
    }
}